@use 'sass:map';
@use '@angular/cdk';
@use '@material/list/evolution-mixins' as mdc-list-mixins;
@use '@material/list/evolution-variables' as mdc-list-variables;
@use '@material/typography/typography' as mdc-typography;
@use '../core/tokens/m2/mat/menu' as tokens-mat-menu;
@use '../core/tokens/token-utils';
@use '../core/mdc-helpers/mdc-helpers';
@use '../core/style/menu-common';
@use '../core/style/button-common';

// Prevent rendering mat-menu as it can affect the flex layout.
mat-menu {
  display: none;
}

.mat-mdc-menu-content {
  @include mdc-list-mixins.list-base($query: structure);

  &,
  .mat-mdc-menu-item .mat-mdc-menu-item-text {
    @include mdc-typography.smooth-font();
    flex: 1;
    white-space: normal;

    @include token-utils.use-tokens(tokens-mat-menu.$prefix, tokens-mat-menu.get-token-slots()) {
      @include token-utils.create-token-slot(font-family, item-label-text-font);
      @include token-utils.create-token-slot(line-height, item-label-text-line-height);
      @include token-utils.create-token-slot(font-size, item-label-text-size);
      @include token-utils.create-token-slot(letter-spacing, item-label-text-tracking);
      @include token-utils.create-token-slot(font-weight, item-label-text-weight);
    }
  }
}

.mat-mdc-menu-panel {
  @include menu-common.base;
  box-sizing: border-box;
  outline: 0;

  @include token-utils.use-tokens(tokens-mat-menu.$prefix, tokens-mat-menu.get-token-slots()) {
    @include token-utils.create-token-slot(border-radius, container-shape);
    @include token-utils.create-token-slot(background-color, container-color);
  }

  // TODO(crisbeto): we don't need this for anything, but it was there when
  // we used MDC's structural styles and removing it leads to sub-pixels
  // differences in text rendering which break a lot of screenshots internally.
  // We should clean it up eventually and re-approve all the screenshots.
  will-change: transform, opacity;

  // Prevent users from interacting with the panel while it's animating. Note that
  // people won't be able to click through it, because the overlay pane will catch the click.
  // This fixes the following issues:
  //  * Users accidentally opening sub-menus when the `overlapTrigger` option is enabled.
  //  * Users accidentally tapping on content inside the sub-menu on touch devices, if the
  //    sub-menu overlaps the trigger. The issue is due to touch devices emulating the
  //    `mouseenter` event by dispatching it on tap.
  &.ng-animating {
    pointer-events: none;
  }

  @include cdk.high-contrast(active, off) {
    outline: solid 1px;
  }
}

.mat-divider {
  // Use margin instead of padding since divider uses border-top for line
  @include token-utils.use-tokens(
    tokens-mat-menu.$prefix,
    tokens-mat-menu.get-token-slots()
  ) {
    color: var(#{token-utils.get-token-variable(divider-color)});
    margin-bottom: var(#{token-utils.get-token-variable(divider-bottom-spacing)});
    margin-top: var(#{token-utils.get-token-variable(divider-top-spacing)});
  }
}

.mat-mdc-menu-item {
  @include mdc-helpers.disable-mdc-fallback-declarations {
    @include mdc-list-mixins.item-base;
    @include token-utils.use-tokens(tokens-mat-menu.$prefix, tokens-mat-menu.get-token-slots()) {
      @include mdc-list-mixins.item-spacing(
        var(#{token-utils.get-token-variable(item-leading-spacing)}),
        var(#{token-utils.get-token-variable(item-trailing-spacing)}),
        $query: mdc-helpers.$mdc-base-styles-query
      );

      // stylelint-disable-next-line selector-class-pattern
      &:has(.material-icons, mat-icon, [matButtonIcon]) {
        @include mdc-list-mixins.item-spacing(
          var(#{token-utils.get-token-variable(item-with-icon-leading-spacing)}),
          var(#{token-utils.get-token-variable(item-with-icon-trailing-spacing)}),
          $query: mdc-helpers.$mdc-base-styles-query
        );
      }
    }
  }

  // MDC's menu items are `<li>` nodes which don't need resets, however ours
  // can be anything, including buttons, so we need to do the reset ourselves.
  @include button-common.reset;
  cursor: pointer;
  width: 100%;
  text-align: left;
  box-sizing: border-box;
  color: inherit;
  font-size: inherit;
  background: none;
  text-decoration: none;
  margin: 0; // Resolves an issue where buttons have an extra 2px margin on Safari.
  align-items: center;

  // Set the `min-height` here ourselves, instead of going through
  // the `mdc-list-one-line-item-density` mixin, because it sets a `height`
  // which doesn't work well with multi-line items.
  $height-config: map.get(mdc-list-variables.$one-line-item-density-config, height);
  min-height: map.get($height-config, default);

  @include token-utils.use-tokens(tokens-mat-menu.$prefix, tokens-mat-menu.get-token-slots()) {
    // The class selector isn't specific enough to overide the link pseudo selectors so we need
    // to target them specifically, otherwise the item color might be overwritten by the user
    // agent resets of the app.
    &, &:visited, &:link {
      @include token-utils.create-token-slot(color, item-label-text-color);
    }

    .mat-icon-no-color,
    .mat-mdc-menu-submenu-icon {
      @include token-utils.create-token-slot(color, item-icon-color);
    }
  }

  &[disabled] {
    cursor: default;

    // This is the same as `mdc-list-mixins.list-disabled-opacity` which
    // we can't use directly, because it comes with some selectors.
    opacity: mdc-list-variables.$content-disabled-opacity;

    // The browser prevents clicks on disabled buttons from propagating which prevents the menu
    // from closing, but clicks on child nodes still propagate which is inconsistent (see #16694).
    // In order to keep the behavior consistent and prevent the menu from closing, we add an overlay
    // on top of the content that will catch all the clicks while disabled.
    &::after {
      display: block;
      position: absolute;
      content: '';
      top: 0;
      left: 0;
      bottom: 0;
      right: 0;
    }
  }

  .mat-icon {
    flex-shrink: 0;
    @include token-utils.use-tokens(tokens-mat-menu.$prefix, tokens-mat-menu.get-token-slots()) {
      margin-right: var(#{token-utils.get-token-variable(item-spacing)});
      height: var(#{token-utils.get-token-variable(item-icon-size)});
      width: var(#{token-utils.get-token-variable(item-icon-size)});
    }
  }

  [dir='rtl'] & {
    text-align: right;

    .mat-icon {
      margin-right: 0;
      @include token-utils.use-tokens(tokens-mat-menu.$prefix, tokens-mat-menu.get-token-slots()) {
        margin-left: var(#{token-utils.get-token-variable(item-spacing)});
      }
    }
  }

  &:not([disabled]) {
    @include token-utils.use-tokens(tokens-mat-menu.$prefix, tokens-mat-menu.get-token-slots()) {
      &:hover {
        @include token-utils.create-token-slot(background-color, item-hover-state-layer-color);
      }

      &.cdk-program-focused,
      &.cdk-keyboard-focused,
      &.mat-mdc-menu-item-highlighted {
        @include token-utils.create-token-slot(background-color, item-focus-state-layer-color);
      }
    }
  }

  @include cdk.high-contrast(active, off) {
    $outline-width: 1px;

    // We need to move the item 1px down, because Firefox seems to have
    // an issue rendering the top part of the outline (see #21524).
    margin-top: $outline-width;
  }
}

.mat-mdc-menu-submenu-icon {
  @include token-utils.use-tokens(tokens-mat-menu.$prefix, tokens-mat-menu.get-token-slots()) {
    @include menu-common.item-submenu-icon(
      var(#{token-utils.get-token-variable(item-spacing)}),
      var(#{token-utils.get-token-variable(item-icon-size)})
    );
  }
}

// Increase specificity because ripple styles are part of the `mat-core` mixin and can
// potentially overwrite the absolute position of the container.
.mat-mdc-menu-item .mat-mdc-menu-ripple {
  @include menu-common.item-ripple;
}
